#ifndef ZPP_STEPPER_HPP
#define ZPP_STEPPER_HPP

#include <chrono>
#include <zephyr/drivers/stepper.h>
#include <zpp/device.hpp>
#include <zpp/error.hpp>

namespace zpp {

class stepper {
public:
  ZPP_SINGLETON(stepper);
  auto move_to(int32_t micro_step) const -> zpp::error {
    return zpp::error{stepper_move_to(m_stepper, micro_step)};
  }
  auto move_by(int32_t micro_step) const -> zpp::error {
    return zpp::error{stepper_move_by(m_stepper, micro_step)};
  }
  auto run(stepper_direction dir) const -> zpp::error {
    return zpp::error{stepper_run(m_stepper, dir)};
  }
  auto stop() const -> zpp::error {
    return zpp::error{stepper_stop(m_stepper)};
  }

  template <typename T_Rep, typename T_Period>
  auto set_interval(std::chrono::duration<T_Rep, T_Period> interval) const
      -> zpp::error {
    const auto ns =
        std::chrono::duration_cast<std::chrono::nanoseconds>(interval).count();
    return zpp::error{stepper_set_microstep_interval(this, ns)};
  }
  auto set_reference_position(int position) {
    return zpp::error{stepper_set_reference_position(m_stepper, position)};
  }

private:
  constexpr stepper(const device *stp) : m_stepper(stp) {}
  const device *m_stepper;
};

} // namespace zpp

#endif